{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Power Flow via PandaModels\n",
    "### PandaModels.jl: Interfacing PowerModels with pandapower\n",
    "\n",
    "This tutorial describes how to run the Power Flow via [PandaModels.jl](https://e2niee.github.io/PandaModels.jl/dev/) calling [PowerModels.jl](https://lanl-ansi.github.io/PowerModels.jl/stable/) package.\n",
    "Power Flow function in PowerModels is built based on [JuMP.jl](https://github.com/jump-dev/JuMP.jl) environment, thus same as OPF we need to set model parameter while calling PF function:\n",
    "\n",
    "* \"ACPPowerModel\": a non-convex nonlinear AC power flow using complex voltages in polar coordinates\n",
    "* \"ACRPowerModel\": a non-convex nonlinear AC power flow using complex voltages in rectangular coordinates\n",
    "* \"SOCWRPowerModel\": a convex quadratic relaxation of the power flow problem\n",
    "* \"DCPPowerModel\": a linear DC approximation of the power flow problem\n",
    "* \"DCMPPowerModel\": a linear DC power flow model with polar voltage variables\n",
    "\n",
    "Note: In order to compare the results of DC-PF between PowerModels and PYPOWER / matpower calculations,\n",
    " you need to set the model to \"DCMPPowerModel\". This direct current model should be equal to the results of matpower calculations,\n",
    "  while model=\"DCPPowerModel\" is the linearized model from AC model. For more information please check [here](https://lanl-ansi.github.io/PowerModels.jl/stable/formulation-details/#PowerModels.DCMPPowerModel)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Let's get started\n",
    "\n",
    "So here is an example of how it works. First, we create a simple grid in pandapower:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import copy\n",
    "import numpy as np\n",
    "from pandapower.runpm import runpm_pf\n",
    "from pandapower.run import runpp\n",
    "from pandapower.networks.simple_pandapower_test_networks import simple_four_bus_system"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net = simple_four_bus_system()\n",
    "net.trafo.loc[0, \"shift_degree\"] = 0."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Then run ac power flow and get voltage angle and amplitude for buses:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    runpm_pf(net, pm_model=\"ACPPowerModel\", calculate_voltage_angles=True)\n",
    "except Exception as err:\n",
    "    print(err)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Also, there more parameters and options that you can add as input while calling the Optimization Problem from PandaModles:\n",
    "\n",
    "| parameter | description | type | default |\n",
    "| :--- | :--- | :---: | :--- |\n",
    "| correct_pm_network_data | checks if network data is correct. If not tries to correct it | bool | True |\n",
    "| silence | Suppresses information and warning messages output by PowerModels | bool | True |\n",
    "| pm_model | PowerModels.jl model to use | str | \"ACPPowerModel\" |\n",
    "| pm_solver | \"main\" solver| str | \"ipopt\" |\n",
    "| pm_mip_solver | mixed integer solver| str | \"cbc\" |\n",
    "| pm_nl_solver | nonlinear solver| str | \"ipopt\" |\n",
    "| pm_tol | default desired convergence tolerance for solver to use | float | 1e-8 |\n",
    "| pm_log_level | solver log level in power models | int | 0 |\n",
    "| delete_buffer_file | If True, the .json file used by PandaModels will be deleted after optimization. | bool | True\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "va_pm = copy.deepcopy(net.res_bus.va_degree)\n",
    "vm_pm = copy.deepcopy(net.res_bus.vm_pu)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "run the powerflow from pypower:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "runpp(net)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "va_pp = copy.deepcopy(net.res_bus.va_degree)\n",
    "vm_pp = copy.deepcopy(net.res_bus.vm_pu)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "lets compare the results:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "np.allclose(va_pm, va_pp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "np.allclose(vm_pm, vm_pp)"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
